home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / tools / jade / src / unix_processes.c < prev    next >
C/C++ Source or Header  |  1995-03-09  |  35KB  |  1,407 lines

  1. /* unix_processes.c -- Subprocess handling for Unix
  2.    Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
  3.  
  4.    This file is part of Jade.
  5.  
  6.    Jade is free software; you can redistribute it and/or modify it
  7.    under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2, or (at your option)
  9.    any later version.
  10.  
  11.    Jade is distributed in the hope that it will be useful, but
  12.    WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with Jade; see the file COPYING.    If not, write to
  18.    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include "jade.h"
  21. #include "jade_protos.h"
  22.  
  23. #include <sys/types.h>
  24. #include <sys/wait.h>
  25. #include <sys/signal.h>
  26. #include <sys/fcntl.h>
  27. #include <sys/time.h>
  28. #include <sys/stat.h>
  29. #include <sys/ioctl.h>
  30. #include <errno.h>
  31. #include <unistd.h>
  32. #include <termios.h>
  33.  
  34. _PR void protect_procs(void);
  35. _PR void unprotect_procs(void);
  36. _PR bool proc_notification(void);
  37. static void check_for_zombies(void);
  38. static void read_from_process(int);
  39. _PR int     write_to_process(VALUE, u_char *, int);
  40. _PR void proc_mark(VALUE);
  41. _PR void proc_sweep(void);
  42. _PR void proc_prin(VALUE, VALUE);
  43. _PR void sigchld_restart(bool);
  44. _PR void proc_init(void);
  45. _PR void proc_kill(void);
  46.  
  47. static struct sigaction chld_sigact;
  48. static sigset_t chld_sigset;
  49.  
  50. struct Proc
  51. {
  52.     u_char    pr_Type;
  53.     char    pr_Status;    /* PR_?? value */
  54.     struct Proc *pr_Next;
  55.     /* Chain of all processes waiting to be notified of a change of state. */
  56.     struct Proc *pr_NotifyNext;
  57.     pid_t    pr_Pid;
  58.     /* pr_Stdin is where we write, pr_Stdout where we read, they may be the
  59.        same.  */
  60.     int        pr_Stdin, pr_Stdout;
  61.     VALUE    pr_OutputStream;
  62.     int        pr_ExitStatus;
  63.     VALUE    pr_NotifyFun;
  64.     VALUE    pr_Prog;
  65.     VALUE    pr_Args;
  66.     VALUE    pr_Dir;
  67.     VALUE    pr_ConnType;
  68. };
  69.  
  70. /* <= 0 means process not running, > 0 means could be running...  */
  71. #define PR_STOPPED  2        /* waiting to be continued */
  72. #define PR_RUNNING  1        /* running merrily */
  73. #define PR_DEAD        0        /* nothing happening on this obj */
  74. #define PR_EXITED  -1        /* process dead but no EOF from pty */
  75.  
  76. /* Connection types, pty-echo is a pty with the ECHO bit set in c_lflag */
  77. static VALUE sym_pipe, sym_pty, sym_pty_echo;
  78.  
  79. #define PR_CONN_PTY_P(p) \
  80.     (((p)->pr_ConnType == sym_pty) || ((p)->pr_ConnType == sym_pty_echo))
  81.  
  82. #define PR_CONN_PTY_ECHO_P(p) \
  83.     ((p)->pr_ConnType == sym_pty_echo)
  84.  
  85. #define PR_CONN_PIPE_P(p) \
  86.     ((p)->pr_ConnType == sym_pipe)
  87.  
  88. /* Handy debugging macro */
  89. #if 0
  90. # define DB(x) fprintf x
  91. #else
  92. # define DB(x)
  93. #endif
  94.  
  95. static struct Proc *process_chain;
  96. static struct Proc *notify_chain;
  97. static int process_run_count;
  98.  
  99. /* This semaphorey thing protects all operations done on process structures
  100.    from SIGCHLD and the process reaping it causes.  */
  101. static int process_mutex = -1;
  102. static bool got_sigchld;
  103.  
  104. INLINE void
  105. protect_procs(void)
  106. {
  107.     process_mutex++;
  108. }
  109.  
  110. void
  111. unprotect_procs(void)
  112. {
  113.     if((process_mutex == 0) && got_sigchld)
  114.     {
  115.     /* Have to leave (process_mutex == 0) while looking for zombies.  */
  116.     got_sigchld = FALSE;
  117.     check_for_zombies();
  118.     }
  119.     process_mutex--;
  120. }
  121.  
  122. /* PR's NotifyFun will be called when possible. This function is safe
  123.    to call from signal handlers.  */
  124. static void
  125. queue_notify(struct Proc *pr)
  126. {
  127.     if(pr->pr_NotifyNext == NULL)
  128.     {
  129.     pr->pr_NotifyNext = notify_chain;
  130.     notify_chain = pr;
  131.     }
  132. }
  133.  
  134. /* Dispatch all queued notification.  */
  135. bool
  136. proc_notification(void)
  137. {
  138.     if(!notify_chain)
  139.     return(FALSE);
  140.     protect_procs();
  141.     cursor(curr_vw, CURS_OFF);
  142.     while(notify_chain != NULL)
  143.     {
  144.     struct Proc *pr = notify_chain;
  145.     notify_chain = pr->pr_NotifyNext;
  146.     pr->pr_NotifyNext = NULL;
  147.     if(pr->pr_NotifyFun && !NILP(pr->pr_NotifyFun))
  148.         funcall(pr->pr_NotifyFun, sym_nil);
  149.     }
  150.     cursor(curr_vw, CURS_ON);
  151.     unprotect_procs();
  152.     return(TRUE);
  153. }
  154.  
  155. /* Checks if any of my children are zombies, takes appropriate action. */
  156. static void
  157. check_for_zombies(void)
  158. {
  159.     int status;
  160.     pid_t pid;
  161.     if(!process_run_count)
  162.     return;
  163.     while((pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0)
  164.     {
  165.     struct Proc *pr = process_chain;
  166. #ifdef DEBUG
  167.     messagef("SIGCHLD: pid %d -- status 0x%x", pid, status);
  168. #endif
  169.     while(pr)
  170.     {
  171.         if((pr->pr_Status > 0) && (pr->pr_Pid == pid))
  172.         break;
  173.         pr = pr->pr_Next;
  174.     }
  175.     if(pr)
  176.     {
  177.         if(WIFSTOPPED(status))
  178.         {
  179.         pr->pr_Status = PR_STOPPED;
  180.         queue_notify(pr);
  181.         }
  182.         else
  183.         {
  184.         pr->pr_ExitStatus = status;
  185.         process_run_count--;
  186.         /* It seems that I can't just nuke the pty once the child's
  187.            dead -- there can be data pending on it still. So, I set
  188.            pr_Status to an in-between value and hope to get an eof
  189.            over pr_Stdin RSN  */
  190.         if((pr->pr_Stdout != 0) || (pr->pr_Stdin != 0))
  191.             pr->pr_Status = PR_EXITED;
  192.         else
  193.         {
  194.             /* No file handles open so just die */
  195.             pr->pr_Status = PR_DEAD;
  196.             queue_notify(pr);
  197.         }
  198.         }
  199.     }
  200.     }
  201. }
  202.  
  203. static void
  204. sigchld_handler(int sig)
  205. {
  206.     if(process_mutex < 0)
  207.     check_for_zombies();
  208.     else
  209.     got_sigchld = TRUE;
  210. }
  211.  
  212. static void
  213. read_from_process(int fd)
  214. {
  215.     struct Proc *pr = process_chain;
  216.     protect_procs();
  217.     while(pr)
  218.     {
  219.     if((pr->pr_Status != PR_DEAD) && (pr->pr_Stdout == fd))
  220.         break;
  221.     pr = pr->pr_Next;
  222.     }
  223.     if(pr)
  224.     {
  225.     u_char buf[1025];
  226.     int actual;
  227.     cursor(curr_vw, CURS_OFF);
  228.     do {
  229.         if((actual = read(fd, buf, 1024)) > 0)
  230.         {
  231.         buf[actual] = 0;
  232.         if(!NILP(pr->pr_OutputStream))
  233.             stream_puts(pr->pr_OutputStream, buf, actual, FALSE);
  234.         }
  235.     } while((actual > 0) || (errno == EINTR));
  236.  
  237.     if((actual <= 0) && (errno != EWOULDBLOCK) && (errno != EAGAIN))
  238.     {
  239.         /* We assume EOF  */
  240. #ifdef HAVE_X11
  241.         FD_CLR(pr->pr_Stdout, &x11_fd_read_set);
  242.         x11_fd_read_action[pr->pr_Stdout] = NULL;
  243. #endif
  244.         close(pr->pr_Stdout);
  245.         if(pr->pr_Stdin && (pr->pr_Stdin != pr->pr_Stdout))
  246.         close(pr->pr_Stdin);
  247.         pr->pr_Stdout = pr->pr_Stdin = 0;
  248.  
  249.         /* This means that the process has already exited and we were
  250.            just waiting for the dregs of its output.  */
  251.         if(pr->pr_Status < 0)
  252.         {
  253.         pr->pr_Status = PR_DEAD;
  254.         queue_notify(pr);
  255.         }
  256.     }
  257.     cursor(curr_vw, CURS_ON);
  258.     }
  259.     unprotect_procs();
  260. }
  261.  
  262. int
  263. write_to_process(VALUE pr, u_char *buf, int bufLen)
  264. {
  265.     int act = 0;
  266.     if(!PROCESSP(pr))
  267.     return(0);
  268.     protect_procs();
  269.     if(VPROC(pr)->pr_Status > 0)
  270.     {
  271.     if(VPROC(pr)->pr_Stdin == 0)
  272.         cmd_signal(sym_process_error, list_2(pr, MKSTR("No link to input")));
  273.     else
  274.     {
  275.         /* This will block */
  276.         act = write(VPROC(pr)->pr_Stdin, buf, bufLen);
  277.         if(act < 0)
  278.         {
  279.         signal_file_error(pr);
  280.         act = 0;
  281.         }
  282.     }
  283.     }
  284.     else
  285.     cmd_signal(sym_process_error, list_2(pr, MKSTR("Not running")));
  286.     unprotect_procs();
  287.     return(act);
  288. }
  289.  
  290. static bool
  291. signal_process(struct Proc *pr, int sig, bool do_grp)
  292. {
  293.     bool rc = TRUE;
  294.     protect_procs();
  295.     if(do_grp)
  296.     {
  297.     if(pr->pr_Stdin && PR_CONN_PTY_P(pr))
  298.     {
  299.         pid_t gid = tcgetpgrp(pr->pr_Stdin);
  300.         if(gid != -1)
  301.         kill(-gid, sig);
  302.         else if(pr->pr_Status != PR_DEAD)
  303.         kill(-pr->pr_Pid, sig);
  304.         else
  305.         rc = FALSE;
  306.     }
  307.     else
  308.     {
  309.         if(pr->pr_Status > 0)
  310.         kill(-pr->pr_Pid, sig);
  311.         else
  312.         rc = FALSE;
  313.     }
  314.     }
  315.     else
  316.     {
  317.     if(pr->pr_Status > 0)
  318.         kill(pr->pr_Pid, sig);
  319.     else
  320.         rc = FALSE;
  321.     }
  322.     unprotect_procs();
  323.     return(rc);
  324. }
  325.  
  326. /* This is only called during GC, when the process isn't being referenced.
  327.    it will already have been taken out of the chain.  */
  328. static void
  329. kill_process(struct Proc *pr)
  330. {
  331.     protect_procs();
  332.     if(pr->pr_Status != PR_DEAD)
  333.     {
  334.     if(pr->pr_Status == PR_RUNNING)
  335.     {
  336.         /* is this too heavy-handed?? */
  337.         if(!signal_process(pr, SIGKILL, TRUE))
  338.         kill(-pr->pr_Pid, SIGKILL);
  339.         waitpid(pr->pr_Pid, &pr->pr_ExitStatus, 0);
  340.         process_run_count--;
  341.     }
  342.     if(pr->pr_Stdout)
  343.     {
  344. #ifdef HAVE_X11
  345.         FD_CLR(pr->pr_Stdout, &x11_fd_read_set);
  346.         x11_fd_read_action[pr->pr_Stdout] = NULL;
  347. #endif
  348.         close(pr->pr_Stdout);
  349.     }
  350.     if(pr->pr_Stdin && (pr->pr_Stdin != pr->pr_Stdout))
  351.         close(pr->pr_Stdin);
  352.     }
  353.     str_free(pr);
  354.     unprotect_procs();
  355. }
  356.  
  357. static int
  358. get_pty(char *slavenam)
  359. {
  360.     char c;
  361.     int i, master;
  362.     struct stat statb;
  363.     for(c = FIRST_PTY_LETTER; c < 'z'; c++)
  364.     {
  365.     for(i = 0; i < 16; i++)
  366.     {
  367.         sprintf(slavenam, "/dev/pty%c%x", c, i);
  368.         if(stat(slavenam, &statb) < 0)
  369.         goto none;
  370.         if((master = open(slavenam, O_RDWR)) >= 0)
  371.         {
  372.         slavenam[sizeof("/dev/")-1] = 't';
  373.         if(access(slavenam, R_OK | W_OK) == 0)
  374.             return(master);
  375.         close(master);
  376.         }
  377.     }
  378.     }
  379. none:
  380.     cmd_signal(sym_process_error, LIST_1(MKSTR("Can't find spare pty")));
  381.     return(-1);
  382. }
  383.  
  384. /* does the dirty stuff of getting the process running. if SYNC_INPUT
  385.    is non-NULL it means to run the process synchronously with it's
  386.    stdin connected to the file SYNC_INPUT. Otherwise this function returns
  387.    immediately after starting the process.  */
  388. static bool
  389. run_process(struct Proc *pr, char **argv, u_char *sync_input)
  390. {
  391.     bool rc = FALSE;
  392.     protect_procs();
  393.     if(pr->pr_Status == PR_DEAD)
  394.     {
  395.     bool usepty = PR_CONN_PTY_P(pr);
  396.     char slavenam[32];
  397.     int stdin_fds[2], stdout_fds[2]; /* only used for pipes */
  398.     pr->pr_ExitStatus = -1;
  399.  
  400.     if(sync_input != NULL)
  401.     {
  402.         usepty = FALSE;
  403.         pr->pr_ConnType = sym_pipe;
  404.         if(pipe(stdout_fds) == 0)
  405.         {
  406.         stdin_fds[0] = open(sync_input, O_RDONLY);
  407.         if(stdin_fds[0] < 0)
  408.         {
  409.             pr->pr_Stdin = 0;
  410.             close(stdout_fds[0]);
  411.             close(stdout_fds[1]);
  412.         }
  413.         else
  414.         {
  415.             pr->pr_Stdin = stdin_fds[0];    /* fake */
  416.             pr->pr_Stdout = stdout_fds[0];
  417.         }
  418.         }
  419.     }
  420.     else if(usepty)
  421.     {
  422.         pr->pr_Stdin = get_pty(slavenam);
  423.         pr->pr_Stdout = pr->pr_Stdin;
  424.     }
  425.     else
  426.     {
  427.         if(pipe(stdin_fds) == 0)
  428.         {
  429.         if(pipe(stdout_fds) == 0)
  430.         {
  431.             pr->pr_Stdin = stdin_fds[1];
  432.             pr->pr_Stdout = stdout_fds[0];
  433.         }
  434.         else
  435.         {
  436.             close(stdin_fds[0]);
  437.             close(stdout_fds[1]);
  438.         }
  439.         }
  440.     }
  441.     if(pr->pr_Stdin)
  442.     {
  443.         switch(pr->pr_Pid = fork())
  444.         {
  445.         case 0:
  446.         if(usepty)
  447.         {
  448.             int slave;
  449.             struct termios st;
  450.             if(setsid() < 0)
  451.             {
  452.             perror("child: setsid()");
  453.             exit(255);
  454.             }
  455.             if((slave = open(slavenam, O_RDWR)) < 0)
  456.             {
  457.             perror("child: open(slave)");
  458.             exit(255);
  459.             }
  460.             close(pr->pr_Stdin);
  461.             dup2(slave, 0);
  462.             dup2(slave, 1);
  463.             dup2(slave, 2);
  464.             if(slave > 2)
  465.             close(slave);
  466. #ifdef TIOCSCTTY
  467.             ioctl(slave, TIOCSCTTY, 0);
  468. #endif
  469.             tcgetattr(0, &st);
  470.             st.c_iflag &= ~(ISTRIP | IGNCR | INLCR | IXOFF);
  471.             st.c_iflag |= (ICRNL | IGNPAR | BRKINT | IXON);
  472.             st.c_oflag &= ~OPOST;
  473.             st.c_cflag &= ~CSIZE;
  474.             st.c_cflag |= CREAD | CS8;
  475.             st.c_lflag &= ~(ECHO | ECHOE | ECHOK | NOFLSH | TOSTOP);
  476.             st.c_lflag |= ISIG;
  477.             if(PR_CONN_PTY_ECHO_P(pr))
  478.             st.c_lflag |= ECHO;
  479.             st.c_cc[VMIN] = 1;
  480.             st.c_cc[VTIME] = 0;
  481.             tcsetattr(0, TCSANOW, &st);
  482.         }
  483.         else
  484.         {
  485.             /* startup for pipes */
  486.             if(setpgid(0, 0) != 0)
  487.             {
  488.             perror("setpgid");
  489.             exit(255);
  490.             }
  491.             dup2(stdin_fds[0], 0);
  492.             close(stdin_fds[0]);
  493.             if(sync_input == NULL)
  494.             close(stdin_fds[1]);
  495.  
  496.             dup2(stdout_fds[1], 1);
  497.             dup2(stdout_fds[1], 2);
  498.             close(stdout_fds[0]);
  499.             close(stdout_fds[1]);
  500.         }
  501.         if(STRINGP(pr->pr_Dir) && (STRING_LEN(pr->pr_Dir) > 0))
  502.             chdir(VSTR(pr->pr_Dir));
  503.         execvp(argv[0], argv);
  504.         perror("child: execvp");
  505.         exit(255);
  506.         case -1:
  507.         perror("fork()");
  508.         break;
  509.         default:
  510.         pr->pr_Status = PR_RUNNING;
  511.         if(!usepty)
  512.         {
  513.             close(stdin_fds[0]);
  514.             close(stdout_fds[1]);
  515.         }
  516.         if(sync_input == NULL)
  517.         {
  518.             if(pr->pr_Stdin == pr->pr_Stdout)
  519.             {
  520.             /* So that pr_Stdout can be made non-blocking
  521.                set up another fd for writing to.  */
  522.             if((pr->pr_Stdin = dup(pr->pr_Stdout)) < 0)
  523.             {
  524.                 /* Maybe this is unwise? */
  525.                 perror("dup(pr->pr_Stdout)");
  526.                 pr->pr_Stdin = pr->pr_Stdout;
  527.             }
  528.             }
  529.             fcntl(pr->pr_Stdin, F_SETFD, 1);
  530.             fcntl(pr->pr_Stdout, F_SETFD, 1);
  531.             fcntl(pr->pr_Stdout, F_SETFL, O_NONBLOCK);
  532. #ifdef HAVE_X11
  533.             FD_SET(pr->pr_Stdout, &x11_fd_read_set);
  534.             x11_fd_read_action[pr->pr_Stdout] = read_from_process;
  535. #endif
  536.             process_run_count++;
  537.         }
  538.         else
  539.         {
  540.             /* Run synchronously.  */
  541.             u_char buf[1025];
  542.             int actual;
  543.             pr->pr_Stdin = 0;
  544.             do {
  545.             actual = read(pr->pr_Stdout, buf, 1024);
  546.             if(actual > 0)
  547.             {
  548.                 buf[actual] = 0;
  549.                 if(!NILP(pr->pr_OutputStream))
  550.                 {
  551.                 stream_puts(pr->pr_OutputStream, buf,
  552.                         actual, FALSE);
  553.                 }
  554.             }
  555.             } while((actual > 0) || (errno == EINTR));
  556.             waitpid(pr->pr_Pid, &pr->pr_ExitStatus, 0);
  557.             close(pr->pr_Stdout);
  558.             pr->pr_Stdout = 0;
  559.             pr->pr_Status = PR_DEAD;
  560.             queue_notify(pr);
  561.         }
  562.         rc = TRUE;
  563.         break;
  564.         }
  565.     }
  566.     }
  567.     else
  568.     {
  569.     cmd_signal(sym_process_error,
  570.            list_2(VAL(pr), MKSTR("Already running")));
  571.     }
  572.     unprotect_procs();
  573.     return(rc);
  574. }
  575.  
  576. void
  577. proc_mark(VALUE pr)
  578. {
  579.     MARKVAL(VPROC(pr)->pr_OutputStream);
  580.     MARKVAL(VPROC(pr)->pr_NotifyFun);
  581.     MARKVAL(VPROC(pr)->pr_Prog);
  582.     MARKVAL(VPROC(pr)->pr_Args);
  583.     MARKVAL(VPROC(pr)->pr_Dir);
  584.     MARKVAL(VPROC(pr)->pr_ConnType);
  585. }
  586.  
  587. void
  588. proc_sweep(void)
  589. {
  590.     struct Proc *pr;
  591.  
  592.     /* First weed out any unused processes from the notify chain...  */
  593.     pr = notify_chain;
  594.     notify_chain = NULL;
  595.     while(pr)
  596.     {
  597.     if(GC_MARKEDP(VAL(pr)))
  598.     {
  599.         pr->pr_NotifyNext = notify_chain;
  600.         notify_chain = pr;
  601.     }
  602.     pr = pr->pr_NotifyNext;
  603.     }
  604.  
  605.     /* ...then do the normal sweep stuff.  */
  606.     pr = process_chain;
  607.     process_chain = NULL;
  608.     while(pr)
  609.     {
  610.     struct Proc *nxt = pr->pr_Next;
  611.     if(!GC_MARKEDP(VAL(pr)))
  612.         kill_process(pr);
  613.     else
  614.     {
  615.         GC_CLR(VAL(pr));
  616.         pr->pr_Next = process_chain;
  617.         process_chain = pr;
  618.     }
  619.     pr = nxt;
  620.     }
  621. }
  622.  
  623. void
  624. proc_prin(VALUE strm, VALUE obj)
  625. {
  626.     struct Proc *pr = VPROC(obj);
  627.     u_char buf[40];
  628.     stream_puts(strm, "#<process", -1, FALSE);
  629.     protect_procs();
  630.     switch(pr->pr_Status)
  631.     {
  632.     case PR_RUNNING:
  633.     stream_puts(strm, " running: ", -1, FALSE);
  634.     stream_puts(strm, VSTR(pr->pr_Prog), -1, TRUE);
  635.     break;
  636.     case PR_STOPPED:
  637.     stream_puts(strm, " stopped: ", -1, FALSE);
  638.     stream_puts(strm, VSTR(pr->pr_Prog), -1, TRUE);
  639.     break;
  640.     case PR_DEAD:
  641.     case PR_EXITED:
  642.     if(pr->pr_ExitStatus != -1)
  643.     {
  644.         sprintf(buf, " exited: 0x%x", pr->pr_ExitStatus);
  645.         stream_puts(strm, buf, -1, FALSE);
  646.         if(pr->pr_Status == PR_EXITED)
  647.         stream_puts(strm, " [waiting for eof]", -1, FALSE);
  648.     }
  649.     break;
  650.     }
  651.     unprotect_procs();
  652.     stream_putc(strm, '>');
  653. }
  654.  
  655. _PR VALUE cmd_make_process(VALUE stream, VALUE fun, VALUE dir, VALUE prog, VALUE args);
  656. DEFUN("make-process", cmd_make_process, subr_make_process, (VALUE stream, VALUE fun, VALUE dir, VALUE prog, VALUE args), V_Subr5, DOC_make_process) /*
  657. ::doc:make_process::
  658. make-process [OUTPUT-STREAM] [FUN] [DIR] [PROGRAM] [ARGS]
  659. <UNIX-ONLY>
  660.  
  661. Creates a new process-object, OUTPUT-STREAM is where all output from this
  662. process goes, FUN is a function to call each time the process running
  663. on this object changes state. DIR is the process' current directory,
  664. PROGRAM the filename of the program to run and ARGS a list of arguments
  665. passed to the process.
  666.  
  667. Any of the arguments may be unspecified, in which case they can be set
  668. either by the functions provided or by the function called to create the
  669. actual running process.
  670. ::end:: */
  671. {
  672.     struct Proc *pr = str_alloc(sizeof(struct Proc));
  673.     if(pr)
  674.     {
  675.     pr->pr_Type = V_Process;
  676.     pr->pr_Next = process_chain;
  677.     process_chain = pr;
  678.     pr->pr_NotifyNext = NULL;
  679.     pr->pr_Status = PR_DEAD;
  680.     pr->pr_Pid = 0;
  681.     pr->pr_Stdin = pr->pr_Stdout = 0;
  682.     pr->pr_ExitStatus = -1;
  683.     pr->pr_OutputStream = stream;
  684.     pr->pr_NotifyFun = fun;
  685.     pr->pr_Prog = prog;
  686.     pr->pr_Args = args;
  687.     pr->pr_Dir = dir;
  688.     pr->pr_ConnType = sym_pipe;
  689.     return(VAL(pr));
  690.     }
  691.     return(mem_error());
  692. }
  693.  
  694. _PR VALUE cmd_start_process(VALUE arg_list);
  695. DEFUN("start-process", cmd_start_process, subr_start_process, (VALUE arg_list), V_SubrN, DOC_start_process) /*
  696. ::doc:start_process::
  697. start-process [PROCESS] [PROGRAM] [ARGS...]
  698. <UNIX-ONLY>
  699.  
  700. Starts a process running on process-object PROCESS. The child-process runs
  701. asynchronously with the editor. If PROCESS is unspecified the make-process
  702. function will be called (with zero arguments) to create one.
  703.  
  704. PROGRAM is the filename of the binary image, it will be searched for in
  705. all directories listed in the `PATH' environment variable.
  706. ARGS are the arguments to give to the process.
  707.  
  708. If any of the optional parameters are unspecified they should have been
  709. set in the PROCESS prior to calling this function.
  710. ::end:: */
  711. {
  712.     struct Proc *pr = NULL;
  713.     VALUE res = sym_nil;
  714.     protect_procs();
  715.     if(CONSP(arg_list))
  716.     {
  717.     if(PROCESSP(VCAR(arg_list)))
  718.         pr = VPROC(VCAR(arg_list));
  719.     arg_list = VCDR(arg_list);
  720.     }
  721.     if(pr == NULL)
  722.     {
  723.     pr = VPROC(cmd_make_process(sym_nil, sym_nil, sym_nil,
  724.                     sym_nil, sym_nil));
  725.     if(pr == NULL)
  726.     {
  727.         unprotect_procs();
  728.         return(NULL);
  729.     }
  730.     }
  731.     if(CONSP(arg_list))
  732.     {
  733.     if(STRINGP(VCAR(arg_list)))
  734.         pr->pr_Prog = VCAR(arg_list);
  735.     arg_list = VCDR(arg_list);
  736.     if(CONSP(arg_list))
  737.         pr->pr_Args = arg_list;
  738.     }
  739.     if(!STRINGP(pr->pr_Prog))
  740.     res = cmd_signal(sym_process_error, list_2(MKSTR("No program"),
  741.                            VAL(pr)));
  742.     else
  743.     {
  744.     int numargs = list_length(pr->pr_Args) + 1;
  745.     char **argv = str_alloc(sizeof(char *) * (numargs + 1));
  746.     if(argv)
  747.     {
  748.         int i;
  749.         arg_list = pr->pr_Args;
  750.         argv[0] = VSTR(pr->pr_Prog);
  751.         for(i = 1; i < numargs; i++)
  752.         {
  753.         if(STRINGP(VCAR(arg_list)))
  754.             argv[i] = VSTR(VCAR(arg_list));
  755.         else
  756.             argv[i] = "";
  757.         arg_list = VCDR(arg_list);
  758.         }
  759.         argv[i] = NULL;
  760.         if(run_process(pr, argv, NULL))
  761.         res = VAL(pr);
  762.         else
  763.         {
  764.         res = cmd_signal(sym_process_error, list_2(MKSTR("Can't start"),
  765.                                VAL(pr)));
  766.         }
  767.         str_free(argv);
  768.     }
  769.     }
  770.     unprotect_procs();
  771.     return(res);
  772. }
  773.  
  774. _PR VALUE cmd_run_process(VALUE arg_list);
  775. DEFUN("run-process", cmd_run_process, subr_run_process, (VALUE arg_list), V_SubrN, DOC_run_process) /*
  776. ::doc:run_process::
  777. run-process [PROCESS] [IN-FILE] [PROGRAM] [ARGS...]
  778. <UNIX-ONLY>
  779.  
  780. Starts a process running on process-object PROCESS. Waits for the child to
  781. exit, then returns the exit-value of the child. If PROCESS is unspecified
  782. the make-process function will be called (with zero arguments) to create one.
  783.  
  784. IN-FILE is the name of the file to connect to the process' standard input,
  785. if this is not defined `/dev/null' is used.
  786. PROGRAM is the filename of the binary image, it will be searched for in
  787. all directories listed in the `PATH' environment variable.
  788. ARGS are the arguments to give to the process.
  789.  
  790. If any of the optional parameters are unspecified they should have been
  791. set in the PROCESS prior to calling this function.
  792. ::end:: */
  793. {
  794.     struct Proc *pr = NULL;
  795.     VALUE res = sym_nil, infile = MKSTR("/dev/null");
  796.     protect_procs();
  797.     if(CONSP(arg_list))
  798.     {
  799.     if(PROCESSP(VCAR(arg_list)))
  800.         pr = VPROC(VCAR(arg_list));
  801.     arg_list = VCDR(arg_list);
  802.     }
  803.     if(pr == NULL)
  804.     {
  805.     pr = VPROC(cmd_make_process(sym_nil, sym_nil, sym_nil,
  806.                     sym_nil, sym_nil));
  807.     if(pr == NULL)
  808.     {
  809.         unprotect_procs();
  810.         return(NULL);
  811.     }
  812.     }
  813.     if(CONSP(arg_list))
  814.     {
  815.     if(STRINGP(VCAR(arg_list)))
  816.         infile = VCAR(arg_list);
  817.     arg_list = VCDR(arg_list);
  818.     if(CONSP(arg_list))
  819.     {
  820.         if(STRINGP(VCAR(arg_list)))
  821.         pr->pr_Prog = VCAR(arg_list);
  822.         arg_list = VCDR(arg_list);
  823.         if(CONSP(arg_list))
  824.         pr->pr_Args = arg_list;
  825.     }
  826.     }
  827.     if(!STRINGP(pr->pr_Prog))
  828.     res = cmd_signal(sym_process_error, LIST_2(MKSTR("No program"),
  829.                            VAL(pr)));
  830.     else if(!file_exists(VSTR(infile)))
  831.     res = signal_file_error(infile);
  832.     else
  833.     {
  834.     int numargs = list_length(pr->pr_Args) + 1;
  835.     char **argv = str_alloc(sizeof(char *) * (numargs + 1));
  836.     if(argv)
  837.     {
  838.         int i;
  839.         arg_list = pr->pr_Args;
  840.         argv[0] = VSTR(pr->pr_Prog);
  841.         for(i = 1; i < numargs; i++)
  842.         {
  843.         if(STRINGP(VCAR(arg_list)))
  844.             argv[i] = VSTR(VCAR(arg_list));
  845.         else
  846.             argv[i] = "";
  847.         arg_list = VCDR(arg_list);
  848.         }
  849.         argv[i] = NULL;
  850.         if(run_process(pr, argv, VSTR(infile)))
  851.         res = make_number(pr->pr_ExitStatus);
  852.         else
  853.         {
  854.         res = cmd_signal(sym_process_error, list_2(MKSTR("Can't run"),
  855.                                VAL(pr)));
  856.         }
  857.         str_free(argv);
  858.     }
  859.     }
  860.     unprotect_procs();
  861.     return(res);
  862. }
  863.  
  864. _PR VALUE cmd_signal_process(VALUE proc, VALUE sig, VALUE grp);
  865. DEFUN("signal-process", cmd_signal_process, subr_signal_process, (VALUE proc, VALUE sig, VALUE grp), V_Subr3, DOC_signal_process) /*
  866. ::doc:signal_process::
  867. signal-process PROCESS SIGNAL [SIGNAL-GROUP]
  868. <UNIX-ONLY>
  869.  
  870. If PROCESS is running asynchronously then send signal number SIGNAL to it.
  871.  
  872. If SIGNAL-GROUP is non-nil also send the signal to all processes in the
  873. process group of PROCESS.
  874. ::end:: */
  875. {
  876.     VALUE res = sym_nil;
  877.     DECLARE1(proc, PROCESSP);
  878.     DECLARE2(sig, NUMBERP);
  879.     protect_procs();
  880.     if(VPROC(proc)->pr_Status > 0)
  881.     {
  882.     if(signal_process(VPROC(proc), VNUM(sig), !NILP(grp)))
  883.         res = sym_t;
  884.     }
  885.     else
  886.     res = cmd_signal(sym_process_error, list_2(proc, MKSTR("Not running")));
  887.     unprotect_procs();
  888.     return(res);
  889. }
  890.  
  891. _PR VALUE cmd_interrupt_process(VALUE proc, VALUE grp);
  892. DEFUN("interrupt-process", cmd_interrupt_process, subr_interrupt_process, (VALUE proc, VALUE grp), V_Subr2, DOC_interrupt_process) /*
  893. ::doc:interrupt_process::
  894. interrupt-process PROCESS [SIGNAL-GROUP]
  895. <UNIX-ONLY>
  896.  
  897. Do (signal-process PROCESS SIGINT SIGNAL-GROUP) or equivalent.
  898. ::end:: */
  899. {
  900.     return(cmd_signal_process(proc, make_number(SIGINT), grp));
  901. }
  902.  
  903. _PR VALUE cmd_kill_process(VALUE proc, VALUE grp);
  904. DEFUN("kill-process", cmd_kill_process, subr_kill_process, (VALUE proc, VALUE grp), V_Subr2, DOC_kill_process) /*
  905. ::doc:kill_process::
  906. kill-process PROCESS [SIGNAL-GROUP]
  907. <UNIX-ONLY>
  908.  
  909. Do (signal-process PROCESS SIGKILL SIGNAL-GROUP) or equivalent.
  910. ::end:: */
  911. {
  912.     return(cmd_signal_process(proc, make_number(SIGKILL), grp));
  913. }
  914.  
  915. _PR VALUE cmd_stop_process(VALUE proc, VALUE grp);
  916. DEFUN("stop-process", cmd_stop_process, subr_stop_process, (VALUE proc, VALUE grp), V_Subr2, DOC_stop_process) /*
  917. ::doc:stop_process::
  918. stop-process PROCESS [SIGNAL-GROUP]
  919. <UNIX-ONLY>
  920.  
  921. Suspends execution of PROCESS, see `continue-process'. If SIGNAL-GROUP is
  922. non-nil also suspends the processes in the process group of PROCESS.
  923. ::end:: */
  924. {
  925.     return(cmd_signal_process(proc, make_number(SIGSTOP), grp));
  926. }
  927.  
  928. _PR VALUE cmd_continue_process(VALUE proc, VALUE grp);
  929. DEFUN("continue-process", cmd_continue_process, subr_continue_process, (VALUE proc, VALUE grp), V_Subr2, DOC_continue_process) /*
  930. ::doc:continue_process::
  931. continue-process PROCESS [SIGNAL-GROUP]
  932. <UNIX-ONLY>
  933.  
  934. Restarts PROCESS after it has been stopped (via `stop-process'). If
  935. SIGNAL-GROUP is non-nil also continues the processes in the process group of
  936. PROCESS.
  937. ::end:: */
  938. {
  939.     VALUE res = sym_t;
  940.     DECLARE1(proc, PROCESSP);
  941.     protect_procs();
  942.     if(VPROC(proc)->pr_Status == PR_STOPPED)
  943.     {
  944.     if(signal_process(VPROC(proc), SIGCONT, !NILP(grp)))
  945.     {
  946.         queue_notify(VPROC(proc));
  947.         VPROC(proc)->pr_Status = PR_RUNNING;
  948.         res = sym_t;
  949.     }
  950.     }
  951.     else
  952.     res = cmd_signal(sym_process_error, list_2(proc, MKSTR("Not stopped")));
  953.     unprotect_procs();
  954.     return(res);
  955. }
  956.  
  957. _PR VALUE cmd_process_exit_status(VALUE proc);
  958. DEFUN("process-exit-status", cmd_process_exit_status, subr_process_exit_status, (VALUE proc), V_Subr1, DOC_process_exit_status) /*
  959. ::doc:process_exit_status::
  960. process-exit-status PROCESS
  961. <UNIX-ONLY>
  962.  
  963. Returns the unprocessed exit-status of the last process to be run on the
  964. process-object PROCESS. If PROCESS is currently running, return nil.
  965. ::end:: */
  966. {
  967.     VALUE res = sym_nil;
  968.     DECLARE1(proc, PROCESSP);
  969.     protect_procs();
  970.     if(VPROC(proc)->pr_Status <= 0)
  971.     {
  972.     if(VPROC(proc)->pr_ExitStatus != -1)
  973.         res = make_number(VPROC(proc)->pr_ExitStatus);
  974.     }
  975.     unprotect_procs();
  976.     return(res);
  977. }
  978.  
  979. _PR VALUE cmd_process_exit_value(VALUE proc);
  980. DEFUN("process-exit-value", cmd_process_exit_value, subr_process_exit_value, (VALUE proc), V_Subr1, DOC_process_exit_value) /*
  981. ::doc:process_exit_value::
  982. process-exit-value PROCESS
  983. <UNIX-ONLY>
  984.  
  985. Returns the return-value of the last process to be run on PROCESS, or nil if:
  986.   a) no process has run on PROCESS
  987.   b) PROCESS is still running
  988.   c) PROCESS exited abnormally
  989. ::end:: */
  990. {
  991.     VALUE res = sym_nil;
  992.     DECLARE1(proc, PROCESSP);
  993.     protect_procs();
  994.     if((VPROC(proc)->pr_Status <= 0) && (VPROC(proc)->pr_ExitStatus != -1))
  995.     res = make_number(WEXITSTATUS(VPROC(proc)->pr_ExitStatus));
  996.     unprotect_procs();
  997.     return(res);
  998. }
  999.  
  1000. _PR VALUE cmd_process_id(VALUE proc);
  1001. DEFUN("process-id", cmd_process_id, subr_process_id, (VALUE proc), V_Subr1, DOC_process_id) /*
  1002. ::doc:process_id::
  1003. process-id PROCESS
  1004. <UNIX-ONLY>
  1005.  
  1006. If PROCESS is running, return the process-identifier associated with it
  1007. (ie, its pid).
  1008. ::end:: */
  1009. {
  1010.     VALUE res = sym_nil;
  1011.     DECLARE1(proc, PROCESSP);
  1012.     protect_procs();
  1013.     if(VPROC(proc)->pr_Status > 0)
  1014.     res = make_number(VPROC(proc)->pr_Pid);
  1015.     unprotect_procs();
  1016.     return(res);
  1017. }
  1018.  
  1019. _PR VALUE cmd_process_running_p(VALUE proc);
  1020. DEFUN("process-running-p", cmd_process_running_p, subr_process_running_p, (VALUE proc), V_Subr1, DOC_process_running_p) /*
  1021. ::doc:process_running_p::
  1022. process-running-p PROCESS
  1023. <UNIX-ONLY>
  1024.  
  1025. Return t if PROCESS is running.
  1026. ::end:: */
  1027. {
  1028.     VALUE res;
  1029.     DECLARE1(proc, PROCESSP);
  1030.     protect_procs();
  1031.     if(VPROC(proc)->pr_Status == PR_RUNNING)
  1032.     res = sym_t;
  1033.     else
  1034.     res = sym_nil;
  1035.     unprotect_procs();
  1036.     return(res);
  1037. }
  1038.  
  1039. _PR VALUE cmd_process_stopped_p(VALUE proc);
  1040. DEFUN("process-stopped-p", cmd_process_stopped_p, subr_process_stopped_p, (VALUE proc), V_Subr1, DOC_process_stopped_p) /*
  1041. ::doc:process_stopped_p::
  1042. process-stopped-p PROCESS
  1043. <UNIX-ONLY>
  1044.  
  1045. Return t if PROCESS has been stopped.
  1046. ::end:: */
  1047. {
  1048.     VALUE res;
  1049.     DECLARE1(proc, PROCESSP);
  1050.     protect_procs();
  1051.     if(VPROC(proc)->pr_Status == PR_STOPPED)
  1052.     res = sym_t;
  1053.     else
  1054.     res = sym_nil;
  1055.     unprotect_procs();
  1056.     return(res);
  1057. }
  1058.  
  1059. _PR VALUE cmd_process_in_use_p(VALUE proc);
  1060. DEFUN("process-in-use-p", cmd_process_in_use_p, subr_process_in_use_p, (VALUE proc), V_Subr1, DOC_process_in_use_p) /*
  1061. ::doc:process_in_use_p::
  1062. process-in-use-p PROCESS
  1063. <UNIX-ONLY>
  1064.  
  1065. Similar to `process-running-p' except that this returns t even when the
  1066. process has stopped, or has exited but the pty connected to `PROCESS' is still
  1067. in use.
  1068. ::end:: */
  1069. {
  1070.     VALUE res;
  1071.     DECLARE1(proc, PROCESSP);
  1072.     protect_procs();
  1073.     if(VPROC(proc)->pr_Status != PR_DEAD)
  1074.     res = sym_t;
  1075.     else
  1076.     res = sym_nil;
  1077.     unprotect_procs();
  1078.     return(res);
  1079. }
  1080.  
  1081. _PR VALUE cmd_processp(VALUE arg);
  1082. DEFUN("processp", cmd_processp, subr_processp, (VALUE arg), V_Subr1, DOC_process_p) /*
  1083. ::doc:process_p::
  1084. processp ARG
  1085. <UNIX-ONLY>
  1086.  
  1087. Return t is ARG is a process-object.
  1088. ::end:: */
  1089. {
  1090.     if(PROCESSP(arg))
  1091.     return(sym_t);
  1092.     return(sym_nil);
  1093. }
  1094.  
  1095. _PR VALUE cmd_process_prog(VALUE proc);
  1096. DEFUN("process-prog", cmd_process_prog, subr_process_prog, (VALUE proc), V_Subr1, DOC_process_prog) /*
  1097. ::doc:process_prog::
  1098. process-prog PROCESS
  1099. <UNIX-ONLY>
  1100.  
  1101. Return the name of the program in PROCESS.
  1102. ::end:: */
  1103. {
  1104.     VALUE res;
  1105.     DECLARE1(proc, PROCESSP);
  1106.     protect_procs();
  1107.     res = VPROC(proc)->pr_Prog;
  1108.     unprotect_procs();
  1109.     return(res);
  1110. }
  1111.  
  1112. _PR VALUE cmd_set_process_prog(VALUE proc, VALUE prog);
  1113. DEFUN("set-process-prog", cmd_set_process_prog, subr_set_process_prog, (VALUE proc, VALUE prog), V_Subr2, DOC_set_process_prog) /*
  1114. ::doc:set_process_prog::
  1115. set-process-prog PROCESS PROGRAM
  1116. <UNIX-ONLY>
  1117.  
  1118. Sets the name of the program to run on PROCESS to FILE.
  1119. ::end:: */
  1120. {
  1121.     DECLARE1(proc, PROCESSP);
  1122.     DECLARE2(prog, STRINGP);
  1123.     protect_procs();
  1124.     VPROC(proc)->pr_Prog = prog;
  1125.     unprotect_procs();
  1126.     return(prog);
  1127. }
  1128.  
  1129. _PR VALUE cmd_process_args(VALUE proc);
  1130. DEFUN("process-args", cmd_process_args, subr_process_args, (VALUE proc), V_Subr1, DOC_process_args) /*
  1131. ::doc:process_args::
  1132. process-args PROCESS
  1133. <UNIX-ONLY>
  1134.  
  1135. Return the list of arguments to PROCESS.
  1136. ::end:: */
  1137. {
  1138.     VALUE res;
  1139.     DECLARE1(proc, PROCESSP);
  1140.     protect_procs();
  1141.     res = VPROC(proc)->pr_Args;
  1142.     unprotect_procs();
  1143.     return(res);
  1144. }
  1145.  
  1146. _PR VALUE cmd_set_process_args(VALUE proc, VALUE args);
  1147. DEFUN("set-process-args", cmd_set_process_args, subr_set_process_args, (VALUE proc, VALUE args), V_Subr2, DOC_set_process_args) /*
  1148. ::doc:set_process_args::
  1149. set-process-args PROCESS ARG-LIST
  1150. <UNIX-ONLY>
  1151.  
  1152. Set the arguments to PROCESS.
  1153. ::end:: */
  1154. {
  1155.     DECLARE1(proc, PROCESSP);
  1156.     if(!NILP(args) && !CONSP(args))
  1157.     return(signal_arg_error(args, 2));
  1158.     protect_procs();
  1159.     VPROC(proc)->pr_Args = args;
  1160.     unprotect_procs();
  1161.     return(args);
  1162. }
  1163.  
  1164. _PR VALUE cmd_process_output_stream(VALUE proc);
  1165. DEFUN("process-output-stream", cmd_process_output_stream, subr_process_output_stream, (VALUE proc), V_Subr1, DOC_process_output_stream) /*
  1166. ::doc:process_output_stream::
  1167. process-output-stream PROCESS
  1168. <UNIX-ONLY>
  1169.  
  1170. Return the stream to which all output from PROCESS is sent.
  1171. ::end:: */
  1172. {
  1173.     VALUE res;
  1174.     DECLARE1(proc, PROCESSP);
  1175.     protect_procs();
  1176.     res = VPROC(proc)->pr_OutputStream;
  1177.     unprotect_procs();
  1178.     return(res);
  1179. }
  1180.  
  1181. _PR VALUE cmd_set_process_output_stream(VALUE proc, VALUE stream);
  1182. DEFUN("set-process-output-stream", cmd_set_process_output_stream, subr_set_process_output_stream, (VALUE proc, VALUE stream), V_Subr2, DOC_set_process_output_stream) /*
  1183. ::doc:set_process_output_stream::
  1184. set-process-output-stream PROCESS STREAM
  1185. <UNIX-ONLY>
  1186.  
  1187. Set the output-stream of PROCESS to STREAM.
  1188. ::end:: */
  1189. {
  1190.     DECLARE1(proc, PROCESSP);
  1191.     protect_procs();
  1192.     VPROC(proc)->pr_OutputStream = stream;
  1193.     unprotect_procs();
  1194.     return(stream);
  1195. }
  1196.  
  1197. _PR VALUE cmd_process_function(VALUE proc);
  1198. DEFUN("process-function", cmd_process_function, subr_process_function, (VALUE proc), V_Subr1, DOC_process_function) /*
  1199. ::doc:process_function::
  1200. process-function PROCESS
  1201. <UNIX-ONLY>
  1202.  
  1203. Return the function which is called when PROCESS changes state (i.e. it
  1204. exits or is stopped).
  1205. ::end:: */
  1206. {
  1207.     VALUE res;
  1208.     DECLARE1(proc, PROCESSP);
  1209.     protect_procs();
  1210.     res = VPROC(proc)->pr_NotifyFun;
  1211.     unprotect_procs();
  1212.     return(res);
  1213. }
  1214.  
  1215. _PR VALUE cmd_set_process_function(VALUE proc, VALUE fn);
  1216. DEFUN("set-process-function", cmd_set_process_function, subr_set_process_function, (VALUE proc, VALUE fn), V_Subr2, DOC_set_process_function) /*
  1217. ::doc:set_process_function::
  1218. set-process-function PROCESS FUNCTION
  1219. <UNIX-ONLY>
  1220.  
  1221. Set the function which is called when PROCESS changes state to FUNCTION.
  1222. ::end:: */
  1223. {
  1224.     DECLARE1(proc, PROCESSP);
  1225.     protect_procs();
  1226.     VPROC(proc)->pr_NotifyFun = fn;
  1227.     unprotect_procs();
  1228.     return(fn);
  1229. }
  1230.  
  1231. _PR VALUE cmd_process_dir(VALUE proc);
  1232. DEFUN("process-dir", cmd_process_dir, subr_process_dir, (VALUE proc), V_Subr1, DOC_process_dir) /*
  1233. ::doc:process_dir::
  1234. process-dir PROCESS
  1235. <UNIX-ONLY>
  1236.  
  1237. Return the name of the directory which becomes the working directory of
  1238. PROCESS when it is started.
  1239. ::end:: */
  1240. {
  1241.     VALUE res;
  1242.     DECLARE1(proc, PROCESSP);
  1243.     protect_procs();
  1244.     res = VPROC(proc)->pr_Dir;
  1245.     unprotect_procs();
  1246.     return(res);
  1247. }
  1248.  
  1249. _PR VALUE cmd_set_process_dir(VALUE proc, VALUE dir);
  1250. DEFUN("set-process-dir", cmd_set_process_dir, subr_set_process_dir, (VALUE proc, VALUE dir), V_Subr2, DOC_set_process_dir) /*
  1251. ::doc:set_process_dir::
  1252. set-process-dir PROCESS DIR
  1253. <UNIX-ONLY>
  1254.  
  1255. Set the directory of PROCESS to DIR.
  1256. ::end:: */
  1257. {
  1258.     DECLARE1(proc, PROCESSP);
  1259.     protect_procs();
  1260.     VPROC(proc)->pr_Dir = dir;
  1261.     unprotect_procs();
  1262.     return(dir);
  1263. }
  1264.  
  1265. _PR VALUE cmd_process_connection_type(VALUE proc);
  1266. DEFUN("process-connection-type", cmd_process_connection_type, subr_process_connection_type, (VALUE proc), V_Subr1, DOC_process_connection_type) /*
  1267. ::doc:process_connection_type::
  1268. process-connection-type PROCESS
  1269. <UNIX-ONLY>
  1270.  
  1271. Returns a symbol defining the type of stream (i.e. pipe or pty) used to
  1272. connect PROCESS with its physical process.
  1273. ::end:: */
  1274. {
  1275.     VALUE res;
  1276.     DECLARE1(proc, PROCESSP);
  1277.     protect_procs();
  1278.     res = VPROC(proc)->pr_ConnType;
  1279.     unprotect_procs();
  1280.     return(res);
  1281. }
  1282.  
  1283. _PR VALUE cmd_set_process_connection_type(VALUE proc, VALUE type);
  1284. DEFUN("set-process-connection-type", cmd_set_process_connection_type, subr_set_process_connection_type, (VALUE proc, VALUE type), V_Subr2, DOC_set_process_connection_type) /*
  1285. ::doc:set_process_connection_type::
  1286. set-process-connection-type PROCESS TYPE
  1287. <UNIX-ONLY>
  1288.  
  1289. Define how PROCESS communicates with it's child process, TYPE can be one of
  1290. the following symbols,
  1291.   pty        Use a pty
  1292.   pty-echo    Similar to `pty' but the ECHO flag is set in the slave
  1293.   pipe        Two pipes are used
  1294.  
  1295. This function can only be used when PROCESS is not in use.
  1296. ::end:: */
  1297. {
  1298.     DECLARE1(proc, PROCESSP);
  1299.     protect_procs();
  1300.     if(VPROC(proc)->pr_Status != PR_DEAD)
  1301.     type = cmd_signal(sym_process_error, list_2(MKSTR("Process in use"),
  1302.                             proc));
  1303.     else
  1304.     VPROC(proc)->pr_ConnType = type;
  1305.     unprotect_procs();
  1306.     return(type);
  1307. }
  1308.  
  1309. /* Turns on or off restarted system calls */
  1310. void
  1311. sigchld_restart(bool flag)
  1312. {
  1313.     if(flag)
  1314.     {
  1315. #ifdef SA_RESTART
  1316.     chld_sigact.sa_flags |= SA_RESTART;
  1317. #else
  1318. # ifdef SA_INTERRUPT
  1319.     chld_sigact.sa_flags &= ~SA_INTERRUPT;
  1320. # endif
  1321. #endif
  1322.     }
  1323.     else
  1324.     {
  1325. #ifdef SA_RESTART
  1326.     chld_sigact.sa_flags &= ~SA_RESTART;
  1327. #else
  1328. # ifdef SA_INTERRUPT
  1329.     chld_sigact.sa_flags |= SA_INTERRUPT;
  1330. # endif
  1331. #endif
  1332.     }
  1333.     sigaction(SIGCHLD, &chld_sigact, NULL);
  1334. }
  1335.  
  1336. void
  1337. proc_init(void)
  1338. {
  1339.     /* Setup SIGCHLD stuff.  */
  1340.     sigemptyset(&chld_sigset);
  1341.     sigaddset(&chld_sigset, SIGCHLD);
  1342.     chld_sigact.sa_handler = sigchld_handler;
  1343.     chld_sigact.sa_mask = chld_sigset;
  1344. #ifdef SA_RESTART
  1345.     chld_sigact.sa_flags = SA_RESTART;
  1346. #else
  1347.     chld_sigact.sa_flags = 0;
  1348. #endif
  1349.     sigaction(SIGCHLD, &chld_sigact, NULL);
  1350.  
  1351.     /* Is this necessary?? Better safe than core-dumped ;-)  */
  1352.     signal(SIGPIPE, SIG_IGN);
  1353.  
  1354.     setpgid(0, 0);
  1355.  
  1356.     INTERN(sym_pipe, "pipe");
  1357.     INTERN(sym_pty, "pty");
  1358.     INTERN(sym_pty_echo, "pty-echo");
  1359.     ADD_SUBR(subr_make_process);
  1360.     ADD_SUBR(subr_start_process);
  1361.     ADD_SUBR(subr_run_process);
  1362.     ADD_SUBR(subr_signal_process);
  1363.     ADD_SUBR(subr_interrupt_process);
  1364.     ADD_SUBR(subr_kill_process);
  1365.     ADD_SUBR(subr_stop_process);
  1366.     ADD_SUBR(subr_continue_process);
  1367.     ADD_SUBR(subr_process_exit_status);
  1368.     ADD_SUBR(subr_process_exit_value);
  1369.     ADD_SUBR(subr_process_id);
  1370.     ADD_SUBR(subr_process_running_p);
  1371.     ADD_SUBR(subr_process_stopped_p);
  1372.     ADD_SUBR(subr_process_in_use_p);
  1373.     ADD_SUBR(subr_processp);
  1374.     ADD_SUBR(subr_process_prog);
  1375.     ADD_SUBR(subr_set_process_prog);
  1376.     ADD_SUBR(subr_process_args);
  1377.     ADD_SUBR(subr_set_process_args);
  1378.     ADD_SUBR(subr_process_output_stream);
  1379.     ADD_SUBR(subr_set_process_output_stream);
  1380.     ADD_SUBR(subr_process_function);
  1381.     ADD_SUBR(subr_set_process_function);
  1382.     ADD_SUBR(subr_process_dir);
  1383.     ADD_SUBR(subr_set_process_dir);
  1384.     ADD_SUBR(subr_process_connection_type);
  1385.     ADD_SUBR(subr_set_process_connection_type);
  1386. }
  1387.  
  1388. void
  1389. proc_kill(void)
  1390. {
  1391.     struct Proc *pr;
  1392.     protect_procs();
  1393.     pr = process_chain;
  1394.     while(pr)
  1395.     {
  1396.     struct Proc *nxt = pr->pr_Next;
  1397.     kill_process(pr);
  1398.     pr = nxt;
  1399.     }
  1400.     process_chain = NULL;
  1401. #if 0
  1402.     /* Don't do this since we're technically dead. */
  1403.     unprotect_procs();
  1404. #endif
  1405.     signal(SIGCHLD, SIG_IGN);
  1406. }
  1407.